package cn.topcodes.tcsf.admin.service.impl;

import cn.topcode.unicorn.utils.StringUtil;
import cn.topcodes.tcsf.admin.commons.domain.ValueRangeConstant;
import cn.topcodes.tcsf.admin.commons.generic.GenericService;
import cn.topcodes.tcsf.admin.commons.generic.LogType;
import cn.topcodes.tcsf.admin.domain.entity.SysRole;
import cn.topcodes.tcsf.admin.domain.entity.SysRolePermRela;
import cn.topcodes.tcsf.admin.mapper.SysRolePermRelaMapper;
import cn.topcodes.tcsf.admin.mapper.SysUserRoleRelaMapper;
import cn.topcodes.tcsf.admin.service.org.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;

@Service
@Transactional(readOnly=true)
public class SysRoleServiceImpl extends GenericService<SysRole> implements SysRoleService {

    @Autowired
    private SysRolePermRelaMapper sysRolePermRelaMapper;

    @Autowired
    private SysUserRoleRelaMapper sysUserRoleRelaMapper;

    /*如果是内置角色，不允许进行删除、标记删除、启用、禁用操作，不允许更新角色代码*/

    @Override
    @Transactional(readOnly = false)
    public SysRole delete(Long id) {
        if(!isBuildInRole(id)) {
            return super.delete(id);
        }
        return null;
    }

    @Override
    @Transactional(readOnly = false)
    public void markDelete(Long id) {
        if(!isBuildInRole(id)) {
            super.markDelete(id);
        }
    }

    @Override
    @Transactional(readOnly = false)
    public void disable(Long id) {
        if(!isBuildInRole(id)) {
            super.disable(id);
        }
    }

    @Override
    @Transactional(readOnly = false)
    public void enable(Long id) {
        if(!isBuildInRole(id)) {
            super.enable(id);
        }
    }

    @Override
    @Transactional(readOnly = false)
    public Long create(SysRole sysRole) {
        sysRole.setCode(sysRole.getName());
        return super.create(sysRole);
    }

    @Override
    @Transactional(readOnly = false)
    public void update(SysRole sysRole) {
        if(isBuildInRole(sysRole.getId()) || StringUtil.isBlank(sysRole.getCode())) {
            SysRole entity = this.findOne(sysRole.getId());
            sysRole.setCode(entity.getCode());
        }
        super.update(sysRole);
    }

    /*开发者角色不可增删改查，超级管理员仅开发者可以进行增删改查*/

    public List<SysRole> findAll(Example example, Long curUserId) {
       filte(example, curUserId);
        return super.findAll(example);
    }

    @Override
    public List<String> getRoleCode(Long userId) {
        return this.sysUserRoleRelaMapper.getRoleCodesByUserId(userId);
    }

    @Override
    public boolean hasRole(Long userId, String roleCode) {
        Assert.notNull(roleCode, "roleCode不能为空");
        List<String> roleCodes = getRoleCode(userId);
        return roleCodes.contains(roleCode);
    }

    /*用于编辑用户时的角色选择*/
    public List<SysRole> select(Long userId) {
        Example example = this.buildExample();

        boolean isDeveloper = hasRole(userId, ValueRangeConstant.BuiltInRole.ROLE_DEVELOPER);
        boolean isSuperAdmin = hasRole(userId, ValueRangeConstant.BuiltInRole.ROLE_SUPER_ADMIN);
        if(!isDeveloper) {
            Example.Criteria criteria = example.createCriteria();
            criteria.andNotEqualTo("code",ValueRangeConstant.BuiltInRole.ROLE_DEVELOPER);
            if(!isSuperAdmin) {
                criteria.andNotEqualTo("code",ValueRangeConstant.BuiltInRole.ROLE_SUPER_ADMIN);
            }
        }
        return super.findAll(example);
    }

    @Override
    @Transactional(readOnly = false)
    public void assignPerm(Long roleId, Long[] permIds) {
        logGeneric(LogType.UPDATE, "为角色分配权限 角色ID：" + roleId + ",权限：" + permIds);
        Example example = new Example(SysRolePermRela.class);
        example.or().andEqualTo("roleId",roleId);
        this.sysRolePermRelaMapper.deleteByExample(example);
        if(permIds != null) {
            for (Long permId : permIds) {
                SysRolePermRela rela = new SysRolePermRela();
                rela.setPermId(permId);
                rela.setRoleId(roleId);
                rela.setCreatedTime(new Date());
                rela.setUpdatedTime(new Date());
                rela.setDataState(ValueRangeConstant.DataState.DATA_STATE_ENABLE);
                this.sysRolePermRelaMapper.insert(rela);
            }
        }
    }

    @Override
    public Long getDeveloperRoleId() {
        Example example = this.buildExample();
        example.or().andEqualTo("code",ValueRangeConstant.BuiltInRole.ROLE_DEVELOPER);
        return this.findOne(example).getId();
    }

    /*判断是否内置角色*/
    private boolean isBuildInRole(Long roleId) {
        SysRole role = this.findOne(roleId);
        if(role != null) {
            if(ValueRangeConstant.BuiltInRole.ROLE_SUPER_ADMIN.equalsIgnoreCase(role.getCode())
                    || ValueRangeConstant.BuiltInRole.ROLE_DEVELOPER.equalsIgnoreCase(role.getCode())
                    || ValueRangeConstant.BuiltInRole.ROLE_ADMIN.equalsIgnoreCase(role.getCode())) {
                return true;
            }
        }
        return false;
    }

    /*开发者角色永不可见，超级管理员角色仅开发者可见*/
    private void filte(Example example, Long curUserId) {
        boolean isDeveloper = this.hasRole(curUserId, ValueRangeConstant.BuiltInRole.ROLE_DEVELOPER);
        List<Example.Criteria> list = example.getOredCriteria();
        if(!isDeveloper) {
            if(list.isEmpty()) {
                Example.Criteria criteria = example.createCriteria();
                criteria.andNotEqualTo("code",ValueRangeConstant.BuiltInRole.ROLE_DEVELOPER);
                criteria.andNotEqualTo("code",ValueRangeConstant.BuiltInRole.ROLE_SUPER_ADMIN);
            }else {
                for(Example.Criteria criteria : list) {
                    criteria.andNotEqualTo("code",ValueRangeConstant.BuiltInRole.ROLE_DEVELOPER);
                    criteria.andNotEqualTo("code",ValueRangeConstant.BuiltInRole.ROLE_SUPER_ADMIN);
                }
            }
        }
    }
}
